package pers.cz.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import pers.cz.cache.BaseDataCache;
import pers.cz.compilation.DynamicCompilationUtil;
import pers.cz.config.UserUtils;
import pers.cz.date.DateUtils;
import pers.cz.encrypt.DesUtil;
import pers.cz.kettle.DataSyncUtil;
import pers.cz.model.*;
import pers.cz.pub.RespBean;
import pers.cz.service.AutoTestCaseService;
import entity.DataBaseParamter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;
import pers.cz.sql.SqlUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @program: PostGirl-panent
 * @description: AutoTestCaseController
 * @author: Cheng Zhi
 * @create: 2021-11-11 09:46
 **/

@RestController
@Scope( "prototype" )
@Api(tags = "自动化案例管理")
@RequestMapping(path = "/api/autoTestCase")
public class AutoTestCaseController {

    @Autowired
    AutoTestCaseService service;

    @Autowired
    private BaseDataCache baseDataCache;

    @Autowired
    UserUtils userUtils;

    @Value("${script.jarpath}")
    private String jarPath; // 从配置文件中获取编译依赖的jar包位置

    @Value("${script.saveclasspath}")
    private String saveClassPath; // 从配置文件中获取保存临时产生class文件位置。

    @ApiOperation(value = "分页查询所有自动化案例")
    @PostMapping(path = "/qureyAllAutoTestCaseByPage")
    public List<AutoTestCase> qureyAllAutoTestCaseByPage(@RequestBody Map map) {
        int pageStart = (int) map.get("pageStart");
        int pageLimit = (int) map.get("pageLimit");
        List<AutoTestCase> autoTestCases = service.queryAllAutoTestCaseByPage(pageStart, pageLimit);
        for (AutoTestCase autoTestCase : autoTestCases) {
            autoTestCase.setUserName(baseDataCache.getAllPostgirlDtl().get(autoTestCase.getUserId()).getRealName());
        }
        return autoTestCases;
    }

    @ApiOperation(value = "获取案例总数")
    @GetMapping(path = "/getCountAutoTestCase")
    public Integer getCountAutoTestCase() {

        return service.qeuryCount();
    }
    @ApiOperation(value = "新增自动化测试案例")
    @PostMapping(path = "/addAutoTestCase")
    public RespBean addAutoTestCase(@RequestBody Map map) {

        Integer publicTemplateId = (Integer) map.get("publicTemplateId");
        String testCaseName = (String) map.get("testCaseName");
        Integer testCaseTemplateId = (Integer) map.get("testCaseTemplateId");
        Integer id = (Integer) map.get("id");

        AutoTestCase autoTestCase = new AutoTestCase();
        autoTestCase.setUserId(userUtils.getCurrentUserId());
        autoTestCase.setCaseName(testCaseName);
        autoTestCase.setPublicTemplateId(publicTemplateId);
        autoTestCase.setTestCaseTemplateId(testCaseTemplateId);
        autoTestCase.setUpdateTime(DateUtil.date());
        autoTestCase.setId(id);

        Integer count = service.addAutoTestCase(autoTestCase);

        return RespBean.ok("成功添加[" + count + "]条");
    }

    @ApiOperation(value = "获取自动化案例的id,用来后续插入")
    @GetMapping(path = "/getAutoTestCaseId")
    public Long getAutoTestCaseId() {

        return service.getSoNbr();
    }

    @ApiOperation(value = "新增自动化测试案例参数")
    @PostMapping(path = "/addTestCaseParam")
    public Integer addTestCaseParam(@RequestBody Map map) {

        Integer testCaseId = (Integer) map.get("testCaseId");
        String paramName = (String) map.get("paramName");
        Object param = map.get("param");
        String ext1 = (String) map.get("ext1"); // 参数类型 如：code、sql、interFace
        Map script = (Map) map.get("script");

        AutoTestCaseParams autoTestCaseParams = new AutoTestCaseParams();
        autoTestCaseParams.setParam(param.toString());
        autoTestCaseParams.setParamName(paramName);
        autoTestCaseParams.setTestCaseId(testCaseId);
        autoTestCaseParams.setUpdatedTime(DateUtil.date());
        autoTestCaseParams.setExt1(ext1);

        AutoTestCaseParamsCode autoTestCaseParamsCode = null;
        AutoTestCaseParamsSql autoTestCaseParamsSql = null;
        AutoTestCaseParamsRegular autoTestCaseParamsRegular = null;
        if ("code".equals(ext1)) {
            autoTestCaseParamsCode = new AutoTestCaseParamsCode();
            autoTestCaseParamsCode.setClassName((String) script.get("className"));
            autoTestCaseParamsCode.setCodeType((String) script.get("codeType"));
            autoTestCaseParamsCode.setMethodName((String) script.get("methodName"));
            autoTestCaseParamsCode.setCode((String) script.get("code"));
            autoTestCaseParamsCode.setCreatedTime(DateUtil.date());
        } else if ("sql".equals(ext1)) {
            autoTestCaseParamsSql = new AutoTestCaseParamsSql();
            autoTestCaseParamsSql.setCreatedTime(DateUtil.date());
            autoTestCaseParamsSql.setSqlCode((String) script.get("sqlCode"));
            autoTestCaseParamsSql.setDataBaseId((Integer) script.get("dataBaseId"));
        } else if ("regular".equals(ext1)) {
            autoTestCaseParamsRegular = new AutoTestCaseParamsRegular();
            autoTestCaseParamsRegular.setCreatedTime(DateUtil.date());
            autoTestCaseParamsRegular.setExpr((String) script.get("expr"));
        }

        return service.addTestCaseParams(autoTestCaseParams, autoTestCaseParamsSql, autoTestCaseParamsCode, autoTestCaseParamsRegular);
    }

    @ApiOperation(value = "新增自动化测试案例检查点")
    @PostMapping(path = "/addTestCaseCheck")
    public Integer addTestCaseCheck(@RequestBody Map map) {

        String checkPoint = (String) map.get("checkPoint");
        String checkPointName = (String) map.get("checkPointName");
        String assertionType = (String) map.get("assertionType");
        Integer testCaseId = (Integer) map.get("testCaseId");

        AutoTestCaseCheck autoTestCaseCheck = new AutoTestCaseCheck();
        autoTestCaseCheck.setTestcaseId(String.valueOf(testCaseId));
        autoTestCaseCheck.setAssertionType(assertionType);
        autoTestCaseCheck.setCheckPoint(checkPoint);
        autoTestCaseCheck.setCheckPointName(checkPointName);
        autoTestCaseCheck.setCreatedTime(DateUtil.date());

        return service.addTestCaseCheck(autoTestCaseCheck);
    }

    @ApiOperation(value = "新增公共参数")
    @PostMapping(path = "/addPublicParams")
    public Integer addPublicParams(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        String paramName = (String) map.get("paramName");
        String param = (String) map.get("param");

        AutoPublicParams autoPublicParams = new AutoPublicParams();
        autoPublicParams.setTestCaseId(testCaseId);
        autoPublicParams.setParamName(paramName);
        autoPublicParams.setParam(param);

        return service.addPublicParams(autoPublicParams);
    }

    @ApiOperation(value = "删除测试案例")
    @PostMapping(path = "/deleteAutoTestCase")
    public RespBean deleteAutoTestCase(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        Integer count = service.deleteAutoTestCase(testCaseId);
        return RespBean.ok("成功删除[" + count + "]条");
    }

    @ApiOperation(value = "批量删除测试案例")
    @PostMapping(path = "/deleteAutoTestCaseBatch")
    public RespBean deleteAutoTestCaseBatch(@RequestBody Map map) {
        List<Integer> ids = (List<Integer>) map.get("ids");
        Integer count = service.deleteAutoTestCaseBatch(ids);
        return RespBean.ok("成功删除[" + count + "]条");
    }

    @ApiOperation(value = "修改时回显检查点")
    @PostMapping(path = "/queryAutoTestCaseCheckByTestCaseId")
    public List<AutoTestCaseCheck> queryAutoTestCaseCheckByTestCaseId(@RequestBody Map map) {

        Integer testCaseId = (Integer) map.get("testCaseId");
        return service.queryAutoTestCaseCheckByTestCaseId(testCaseId);
    }

    @ApiOperation(value = "修改检查点")
    @PostMapping(path = "/updateAutoTestCaseCheck")
    public Integer updateAutoTestCaseCheck(@RequestBody Map map) {

        String checkPoint = (String) map.get("checkPoint");
        String checkPointName = (String) map.get("checkPointName");
        String assertionType = (String) map.get("assertionType");
        Integer id = (Integer) map.get("id");
        Integer testCaseId = (Integer) map.get("testCaseId");

        AutoTestCaseCheck autoTestCaseCheck = new AutoTestCaseCheck();
        autoTestCaseCheck.setId(id);
        autoTestCaseCheck.setCheckPoint(checkPoint);
        autoTestCaseCheck.setCheckPointName(checkPointName);
        autoTestCaseCheck.setAssertionType(assertionType);
        autoTestCaseCheck.setCreatedTime(DateUtil.date());
        autoTestCaseCheck.setTestcaseId(String.valueOf(testCaseId));
        return service.updateAutoTestCaseCheck(autoTestCaseCheck);
    }

    @ApiOperation(value = "删除检查点")
    @PostMapping(path = "/deleteAutoTestCaseCheck")
    public void deleteAutoTestCaseCheck(@RequestBody Map map) {

        Integer id = (Integer) map.get("id");
        service.deleteAutoTestCaseCheckById(id);
    }

    @ApiOperation(value = "获取测试入参用于回显")
    @PostMapping(path = "/queryAutoTestCaseParams")
    public List<AutoTestCaseParams> queryAutoTestCaseParams(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        return service.queryAutoTestCaseParams(testCaseId);
    }

    @ApiOperation(value = "获取公共入参用于回显")
    @PostMapping(path = "/queryAutoPublicParams")
    public List<AutoPublicParams> queryAutoPublicParams(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        return service.queryAutoPublicParams(testCaseId);
    }

    @ApiOperation(value = "修改测试入参")
    @PostMapping(path = "/updateAutoTestCaseParams")
    public Integer updateAutoTestCaseParams(@RequestBody Map map) {

        //Integer testCaseId = (Integer) map.get("testCaseId");
        Integer id = (Integer) map.get("id");
        String paramName = (String) map.get("paramName");
        String param = (String) map.get("param");
        String ext1 = (String) map.get("ext1");

        AutoTestCaseParams autoTestCaseParams = new AutoTestCaseParams();
        autoTestCaseParams.setParam(param);
        autoTestCaseParams.setId(id);
        autoTestCaseParams.setExt1(ext1);
        //autoTestCaseParams.setParamName(paramName);
        //autoTestCaseParams.setTestCaseId(testCaseId);
        autoTestCaseParams.setUpdatedTime(DateUtil.date());
        return service.updateAutoTestCaseParams(autoTestCaseParams);
    }

    @ApiOperation(value = "修改公共入参")
    @PostMapping(path = "/updateAutoPublicParams")
    public Integer updateAutoPublicParams(@RequestBody Map map) {

        Integer testCaseId = (Integer) map.get("testCaseId");
        Integer id = (Integer) map.get("id");
        String paramName = (String) map.get("paramName");
        String param = (String) map.get("param");

        AutoPublicParams autoPublicParams = new AutoPublicParams();
        autoPublicParams.setId(id);
        autoPublicParams.setTestCaseId(testCaseId);
        autoPublicParams.setParamName(paramName);
        autoPublicParams.setParam(param);

        return service.updateAutoPublicParams(autoPublicParams);
    }

    @ApiOperation(value = "模糊查询案例")
    @PostMapping(path = "/selectAutoTestCaseByFuzzy")
    public List<AutoTestCase> selectAutoTestCaseByFuzzy(@RequestBody Map map) {

        String testCaseName = (String) map.get("testCaseName");
        return service.selectAutoTestCaseByFuzzy(testCaseName);
    }

    @ApiOperation(value = "查询所有的测试案例编号和案例名称")
    @GetMapping("/queryAllIdAndCaseName")
    public Map<Integer,List<String>> queryAllIdAndCaseName(HttpServletRequest request) {

        Map<Integer,List<String>> map = new HashMap<>(); // 这里最好指定一下Map的大小？
        map = service.selectAllIdAndCaseName();
        return map;
    }

    @ApiOperation(value = "调试java脚本代码")
    @PostMapping("/debugScript")
    public Object debugScript(@RequestBody Map map) {

        // 脚本内容
        String javaScript = (String) map.get("javaScript");
        // 脚本依赖jar包的存放路径 从配置文件中获取
        String myJarPath = jarPath;
        // java脚本的全类名
        String className = (String) map.get("className");
        // 要执行的方法名
        String methodName = (String) map.get("methodName");
        // 编译后的文件保存路径
        String mySaveCalssPath = saveClassPath;

        String[] split = className.split("\\.");
        String runClassName = split[split.length-1];

        DynamicCompilationUtil dynamicCompilationUtil = new DynamicCompilationUtil();

        try {
            // 编译文件
            String compilateionResult = dynamicCompilationUtil.compileJava(javaScript, myJarPath, mySaveCalssPath, runClassName.trim());

            if ("success".equals(compilateionResult)) {
                // 编译成功再执行
                // 反射执行
                Object object = dynamicCompilationUtil.loadAndDebugClass(mySaveCalssPath, methodName.trim(), className.trim());
                return object;
            }

            return compilateionResult;
        } catch (Exception e) {
            // 解析异常
            e.printStackTrace();
        }

        return "执行失败";
    }

    @ApiOperation(value = "保存脚本")
    @PostMapping("/saveCode")
    public Integer saveCode(@RequestBody Map map) {

        String code = (String) map.get("code");             // 代码内容
        String codeType = (String) map.get("codeType");     // 代码类型
        String className = (String) map.get("className");   // 类全名
        String methodName = (String) map.get("methodName"); // 要执行的方法名
        Integer paramId = (Integer) map.get("paramId");     // 参数id

        AutoTestCaseParamsCode autoTestCaseParamsCode = new AutoTestCaseParamsCode();

        autoTestCaseParamsCode.setClassName(className);
        autoTestCaseParamsCode.setMethodName(methodName);
        autoTestCaseParamsCode.setCode(code);
        autoTestCaseParamsCode.setCodeType(codeType);
        autoTestCaseParamsCode.setCreatedTime(DateUtil.date());
        autoTestCaseParamsCode.setParamId(paramId);

        return service.saveCode(autoTestCaseParamsCode);
    }

    @ApiOperation(value = "修改脚本")
    @PostMapping("/updateCode")
    public Integer updateCode(@RequestBody Map map) {

        String code = (String) map.get("code");             // 代码内容
        String codeType = (String) map.get("codeType");     // 代码类型
        String className = (String) map.get("className");   // 类全名
        String methodName = (String) map.get("methodName"); // 要执行的方法名
        Integer paramId = (Integer) map.get("paramId");     // 参数id

        AutoTestCaseParamsCode autoTestCaseParamsCode = new AutoTestCaseParamsCode();

        autoTestCaseParamsCode.setClassName(className);
        autoTestCaseParamsCode.setMethodName(methodName);
        autoTestCaseParamsCode.setCode(code);
        autoTestCaseParamsCode.setCodeType(codeType);
        autoTestCaseParamsCode.setCreatedTime(DateUtil.date());
        autoTestCaseParamsCode.setParamId(paramId);

        return service.updateCode(autoTestCaseParamsCode);
    }

    @ApiOperation(value = "调试sql脚本代码")
    @PostMapping("/debugSql")
    public Object executeSql(@RequestBody Map map) {

        String str = JSON.toJSONString(map.get("paramterTarget")); //转化成JSON字符串
        DataBaseParamter paramter  = JSON.parseObject(str,DataBaseParamter.class); //将JSON转化成对象
        paramter.setPassword(DesUtil.decode(paramter.getPassword())); // 解密
        String sql = (String) map.get("sql");
        List<String> results = null;
        try {
            results = DataSyncUtil.executeSql(paramter, sql);
        } catch (Exception e) {
            //e.printStackTrace();
            return e.getMessage();
        }
        return results;
    }

    @ApiOperation(value = "保存sql脚本")
    @PostMapping("/saveSql")
    public Integer saveSql(@RequestBody Map map) {

        String sqlCode = (String) map.get("sqlCode");               // 脚本内容
        Integer dataBaseId = (Integer) map.get("dataBaseId");       // 数据库id
        Integer paramId = (Integer) map.get("paramId");             // 参数id

        AutoTestCaseParamsSql autoTestCaseParamsSql = new AutoTestCaseParamsSql();
        autoTestCaseParamsSql.setCreatedTime(DateUtil.date());
        autoTestCaseParamsSql.setDataBaseId(dataBaseId);
        autoTestCaseParamsSql.setParamId(paramId);
        autoTestCaseParamsSql.setSqlCode(sqlCode);

        return service.saveSqlCode(autoTestCaseParamsSql);
    }

    @ApiOperation(value = "修改sql脚本")
    @PostMapping("/updateSql")
    public Integer updateSql(@RequestBody Map map) {

        String sqlCode = (String) map.get("sqlCode");               // 脚本内容
        Integer dataBaseId = (Integer) map.get("dataBaseId");       // 数据库id
        Integer paramId = (Integer) map.get("paramId");             // 参数id

        AutoTestCaseParamsSql autoTestCaseParamsSql = new AutoTestCaseParamsSql();
        autoTestCaseParamsSql.setCreatedTime(DateUtil.date());
        autoTestCaseParamsSql.setDataBaseId(dataBaseId);
        autoTestCaseParamsSql.setParamId(paramId);
        autoTestCaseParamsSql.setSqlCode(sqlCode);

        return service.updateSqlCode(autoTestCaseParamsSql);
    }

    @ApiOperation(value = "修改正则表达式")
    @PostMapping("/updateRegularExpr")
    public Integer updateRegularExpr(@RequestBody Map map) {

        String expr = (String) map.get("expr");               // 脚本内容
        Integer paramId = (Integer) map.get("paramId");             // 参数id

        AutoTestCaseParamsRegular autoTestCaseParamsRegular = new AutoTestCaseParamsRegular();
        autoTestCaseParamsRegular.setCreatedTime(DateUtil.date());
        autoTestCaseParamsRegular.setParamId(paramId);
        autoTestCaseParamsRegular.setExpr(expr);

        return service.updateRegularExpr(autoTestCaseParamsRegular);
    }

    @ApiOperation(value = "查询脚本")
    @PostMapping("/queryCode")
    public AutoTestCaseParamsCode queryCode(@RequestBody Map map) {

        Integer paramId = (Integer) map.get("paramId");
        return service.queryCode(paramId);
    }

    @ApiOperation(value = "查询sql脚本")
    @PostMapping("/querySqlCode")
    public AutoTestCaseParamsSql querySqlCode(@RequestBody Map map) {

        Integer paramId = (Integer) map.get("paramId");
        return service.querySqlCode(paramId);
    }

    @ApiOperation(value = "删除sql模板")
    @PostMapping("/deleteSqlTemplateById")
    public RespBean deleteSqlTemplateById(@RequestBody Map map) {
        Integer templateId = (Integer) map.get("id");
        Integer count = service.deleteSqlTemplateById(templateId);
        return RespBean.ok("删除成功["  + count + "]条！");
    }

    @ApiOperation(value = "修改sql模板")
    @PostMapping("/udpateSqlTemplate")
    public RespBean udpateSqlTemplate(@RequestBody Map map) {
        Integer templateId = (Integer) map.get("id");
        String sql = (String) map.get("run_sql");
        AutoCollectTestCaseSql autoCollectTestCaseSql = new AutoCollectTestCaseSql();
        autoCollectTestCaseSql.setId(templateId);
        autoCollectTestCaseSql.setRunSql(SqlUtils.purgeSql(sql));
        Integer count = service.updateSqlTemplate(autoCollectTestCaseSql);
        return RespBean.ok("修改成功["  + count + "]条！");
    }

    @ApiOperation(value = "增加sql模板")
    @PostMapping("/addSqlTemplate")
    public RespBean addSqlTemplate(@RequestBody Map map) {
        String busiCode = (String) map.get("busiCode");
        String sql = (String) map.get("sql");
        AutoCollectTestCaseSql autoCollectTestCaseSql = new AutoCollectTestCaseSql();
        autoCollectTestCaseSql.setRunSql(SqlUtils.purgeSql(sql));
        autoCollectTestCaseSql.setBusiCode(busiCode);
        String currentTimestamp = DateUtils.getCurrentTimestamp().toString();
        autoCollectTestCaseSql.setRunTime(currentTimestamp);
        Integer count = service.addSqlTemplate(autoCollectTestCaseSql);
        return RespBean.ok("保存成功["  + count + "]条！");
    }

    @ApiOperation(value = "增加前置检查sql")
    @PostMapping("/addCheckSqls")
    public void addCheckSqls(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        List<Map> sqls = (List<Map>) map.get("sqls");
        List<AutoTestCaseCheckSql> autoTestCaseCheckSqls = new ArrayList<AutoTestCaseCheckSql>();
        sqls.forEach(sql ->{
            if (sql != null) {
                AutoTestCaseCheckSql autoTestCaseCheckSql = new AutoTestCaseCheckSql();
                autoTestCaseCheckSql.setRunSql((String) sql.get("value"));
                autoTestCaseCheckSql.setTestCaseId(testCaseId);
                autoTestCaseCheckSql.setCreatedDate(new Date());
                autoTestCaseCheckSql.setSoDate(new Date());
                autoTestCaseCheckSql.setExt1((String) sql.get("ext1"));
                autoTestCaseCheckSqls.add(autoTestCaseCheckSql);
            }
        });
        service.addAutoCheckSqls(autoTestCaseCheckSqls);
    }


    @ApiOperation(value = "查询所有前置检查sql")
    @PostMapping("/findChcekSqlsByTestCaseId")
    public List<AutoTestCaseCheckSql> findChcekSqlsByTestCaseId(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        return service.findChcekSqlsByTestCaseId(testCaseId);
    }

    @ApiOperation(value = "修改所有前置检查sql")
    @PostMapping("/updateChcekSql")
    public int updateChcekSql(@RequestBody Map map) {
        Integer testCaseId = (Integer) map.get("testCaseId");
        Map sql = (Map) map.get("runSql");
        if (map.get("id") != null) {
            // 如果id不等于null，说明是修改
            AutoTestCaseCheckSql autoTestCaseCheckSql = new AutoTestCaseCheckSql();
            autoTestCaseCheckSql.setRunSql((String) sql.get("value"));
            autoTestCaseCheckSql.setId((Integer) map.get("id"));
            autoTestCaseCheckSql.setTestCaseId(testCaseId);
            autoTestCaseCheckSql.setExt1((String) sql.get("ext1"));
            autoTestCaseCheckSql.setSoDate(DateUtil.date());
            return service.updateChcekSql(autoTestCaseCheckSql);
        }

        AutoTestCaseCheckSql autoTestCaseCheckSql = new AutoTestCaseCheckSql();
        autoTestCaseCheckSql.setRunSql((String) sql.get("value"));
        autoTestCaseCheckSql.setTestCaseId(testCaseId);
        autoTestCaseCheckSql.setSoDate(DateUtil.date());
        autoTestCaseCheckSql.setExt1((String) sql.get("ext1"));
        autoTestCaseCheckSql.setCreatedDate(DateUtil.date());
        return service.addAutoCheckSql(autoTestCaseCheckSql);
    }

    @ApiOperation(value = "删除sql")
    @PostMapping("/deleteCheckSqlById")
    public RespBean deleteCheckSqlById(@RequestBody Map map) {
        Integer id = (Integer) map.get("id");
        Integer count = service.deleteCheckSqlById(id);
        return RespBean.ok("删除成功["  + count + "]条！");
    }
}
